/***************************************************************************
 *   Copyright © 2010 by Nikolay Kornaev                                   *
 *   n.kornaev@gmail.com                                                   *
 *                                                                         *
 *                    This file is part of neuma.                          *
 *                                                                         *
 *   neuma is free software; you can redistribute it and/or modify it      *
 *   under the terms of the GNU General Public License as published by     *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   neuma is distributed in the hope that it will be useful,              *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, see <http://www.gnu.org/licenses/>   *
 ***************************************************************************/

#include <QtCore>
#include <QtGui>

#include "DisplayWidget.h"
#include "MainWindow.h"
#include "SettingsHandler.h"
#include "SettingsDialog.h"
#include "constants.h"
#include "Interface_SourceParser.h"

namespace Neuma
{
  MainWindow::MainWindow(const QString &fileName) :
    printer(QPrinter::HighResolution)
  {
    setupUi(this);
    set = new SettingsHandler();
    teSource->setAcceptRichText(false);
    teSource->setTabStopWidth(30);
    setCentralWidget(&widget);
    widget.init(&printer);

    connect(widget.preview, SIGNAL(paintRequested(QPrinter*)), SLOT(draw(QPrinter*)));
    connect(teSource->document(), SIGNAL(contentsChanged()), SLOT(documentWasModified()));

    connect(aExportBMP, SIGNAL(triggered()), SLOT(processExport()));
    connect(aExportJPG, SIGNAL(triggered()), SLOT(processExport()));
    connect(aExportPNG, SIGNAL(triggered()), SLOT(processExport()));
    connect(aExportTIF, SIGNAL(triggered()), SLOT(processExport()));
    loadPlugins();
    fillUi();
    data = new NeumasData;
    setCurrentFile(""); /// должен вызываться до обновления, иначе в консоль выводится инфа о пустом заголовке

    if (fileName.isEmpty())
      emptyLoad();
    else loadFile(fileName);

    highlighter = currentSP->syntaxHighLighter(teSource->document());
  }

  void MainWindow::emptyLoad()
  {
    currentSP = plugins.value(N_DEFAULT_TYPE);
    if (!currentSP)
    {
      QMessageBox::warning(this, N_APP_NAME, tr("Невозможно найти плагин \"по умолчанию\"."));
      debug("Can't load \"sp_plain\". Application will now quit.", QtCriticalMsg);
      qApp->exit();
    }
    on_aRefresh_triggered();
  }

  void MainWindow::fillUi()
  {
    qreal mL = set->val(PageMarginLeft).toDouble();
    qreal mT = set->val(PageMarginTop).toDouble();
    qreal mR = set->val(PageMarginRight).toDouble();
    qreal mB = set->val(PageMarginBottom).toDouble();
    printer.setPageMargins(mL, mT, mR, mB, QPrinter::Millimeter);
    printer.setPageSize((QPrinter::PaperSize) set->val(PageSize).toInt());
    printer.setOrientation((QPrinter::Orientation) set->val(PageOrientation).toInt());
  }

  void MainWindow::writeSettings()
  {
    qreal mL, mT, mR, mB;
    printer.getPageMargins(&mL, &mT, &mR, &mB, QPrinter::Millimeter);
    set->setVal(PageMarginTop, mT);
    set->setVal(PageMarginRight, mR);
    set->setVal(PageMarginBottom, mB);
    set->setVal(PageMarginLeft, mL);

    set->setVal(PageSize, printer.paperSize());
    set->setVal(PageOrientation, printer.orientation());

    set->writeSettings();
  }

  void MainWindow::closeEvent(QCloseEvent *event)
  {
    if (maybeSave())
    {
      writeSettings();
      event->accept();
    }
    else event->ignore();
  }

  void MainWindow::on_aAbout_triggered()
  {
    QMessageBox::about(this, N_APP_NAME, tr("Программа для конвертации <b>знамён</b> в графику"));
  }

  void MainWindow::on_aAboutQt_triggered()
  {
    qApp->aboutQt();
  }

  void MainWindow::on_aPrint_triggered()
  {
    QPrintPreviewDialog preview(&printer, this);
    connect(&preview, SIGNAL(paintRequested(QPrinter*)), SLOT(draw(QPrinter*)));
    preview.exec();
  }

  //void on_aExportPDF_triggered();

  void MainWindow::on_aSettings_triggered()
  {
    SettingsDialog *d = new SettingsDialog(set, this);
    if (d->exec() != QDialog::Accepted)
      return;
    set->setVal(RendererSpaceBlocksHorizontal, d->sbHorizontalOffset->value());
    set->setVal(RendererSpaceBlocksVertical, d->sbVerticalOffset->value());
    set->setVal(RendererSpaceLines, d->sbLinesSpace->value());

    set->setVal(RendererFontNameNeuma, d->cbFontNeuma->currentText());
    set->setVal(RendererFontNameSyllabe, d->cbFontSyllabe->currentText());
    set->setVal(RendererFontsListNeuma, d->collectComboBox(d->cbFontNeuma));
    set->setVal(RendererFontsListSyllabe, d->collectComboBox(d->cbFontSyllabe));

    set->setVal(RendererFontSizeNeuma, d->sbFontSizeNeuma->value());
    set->setVal(RendererFontSizeSyllabe, d->sbFontSizeSyllabe->value());

    set->setVal(RendererFontColorNeuma, d->leColorPreviewNeuma->text());
    set->setVal(RendererFontColorMarks, d->leColorPreviewMarks->text());
    set->setVal(RendererFontColorSyllabe, d->leColorPreviewSyllabe->text());

    set->setVal(RendererOutlineColorPage, d->leColorPreviewOutlinePage->text());
    set->setVal(RendererOutlineColorNeuma, d->leColorPreviewOutlineNeuma->text());
    set->setVal(RendererOutlineColorSyllabe, d->leColorPreviewOutlineSyllabe->text());

    set->setVal(RendererOutlinePage, d->chOutlinePage->isChecked());
    set->setVal(RendererOutlineNeuma, d->chOutlineNeuma->isChecked());
    set->setVal(RendererOutlineSyllabe, d->chOutlineSyllabe->isChecked());

    set->setVal(RendererExportResolution, d->leExportResolution->text().toInt());
    set->setVal(RendererNeumaOverSyllabe, d->cbNeumaOverSyllabe->isChecked());
    set->setVal(RendererNeumaTruncateMarks, d->cbNeumaTruncateMarks->isChecked());

    on_aRefresh_triggered();
  }

  void MainWindow::loadPlugins()
  {
    pluginsDir = QDir(qApp->applicationDirPath());
    pluginsDir.cdUp();

    QStringList possibleDirs;

    if (pluginsDir.exists("lib"))
      possibleDirs.append("lib");
    if (pluginsDir.exists("lib64"))
      possibleDirs.append("lib64");

    if (possibleDirs.isEmpty())
    {
      exitOnError(tr("Не найдена директория поиска плагинов."));
    }

    foreach (QString dir, possibleDirs)
      {
	pluginsDir.cd(dir);
	pluginsDir.cd("neuma");
	pluginsDir.cd("plugins");
	debug(QString("Ищем плагины в \"%1\"").arg(pluginsDir.absolutePath()));
	foreach (QString fileName, pluginsDir.entryList(QDir::Files))
	  {
	    QPluginLoader loader(pluginsDir.absoluteFilePath(fileName));
	    QObject *plugin = loader.instance();
	    if (plugin)
	      {
		SourceParser *sp = qobject_cast<SourceParser *> (plugin);
		plugins.insert(sp->supportedExtension(), sp);
		debug(QString(" Загружен плагин:\t\"%1\"\t(%2)").arg(fileName).arg(sp->pluginName()));
	      }
	    else debug(QString(" Пропускаем файл\t\"%1\"").arg(fileName));
	  }
	debug(QString("Завершён поиск плагинов в \"%1\"").arg(pluginsDir.absolutePath()));
      }
    if (!plugins.contains(N_DEFAULT_TYPE))
      exitOnError(tr("Не найден плагин \"по умолчанию\". Путь поиска: \"%1\"").arg(pluginsDir.absolutePath()));
  }

  void MainWindow::exitOnError(const QString &message)
  {
    debug(message, QtCriticalMsg);
    QMessageBox::critical(this, N_APP_NAME, message);
    debug("Приложение завершает работу.", QtCriticalMsg);
    exit(1);
  }
}
